

import java.net.InetAddress;
import java.util.ArrayList;
import java.util.List;

import javax.media.rtp.*;
import javax.media.rtp.rtcp.*;
import javax.media.*;
import javax.media.protocol.*;
import javax.media.control.*;

public class RTPServer implements ControllerListener, Runnable {
	private boolean realized = false;
	private boolean configured = false;
	private boolean createPlayer = false;
	Processor p;
	MediaLocator src;
	MediaLocator src1;
	private List<RadioPeer.Peer> children;

	public static void main (String[] args) {
//		RTPServer rtp = new RTPServer("10.11.38.130","file:///C:/01_Intro.wav");
		startStream("file:///C:/Stan.wav", "file:///C:/Stan.wav" , new ArrayList<RadioPeer.Peer>() , true);
//		startStream("10.11.38.245", 49150 ,"rtp://10.11.38.247:49152/audio", false);
//		startStream("10.11.38.245", 49160, "rtp://10.11.38.247:49156/audio", true);
	}
	
	public static void startStream( String mediaToStreamFrom, String otherToStreamFrom, List<RadioPeer.Peer> children, boolean startPlayer){
		RTPServer rtp = new RTPServer(mediaToStreamFrom, otherToStreamFrom, startPlayer, children);
		Thread t = new Thread(rtp);
		t.start();
	}

	public RTPServer( String srcFile, String srcStream, boolean createPlayer, List<RadioPeer.Peer> children) {

		this.children = children;
		src = new MediaLocator(srcFile);
		src1 = new MediaLocator(srcStream);
		this.createPlayer = createPlayer;
	}
	
	public void createPlayer(){
		try {
			Player player = Manager.createRealizedPlayer(src1);
			player.addControllerListener(this);
			player.start();
		} catch(Exception e) {
			e.printStackTrace();
			System.exit(1);
		}
	}

	private void setTrackFormat(Processor p) {
		// Get the tracks from the processor
		TrackControl [] tracks = p.getTrackControls();
		// Do we have atleast one track?
		if (tracks == null || tracks.length < 1) {
			System.out.println("Couldn't find tracks in processor");
			System.exit(1);
		}

		// Set the output content descriptor to RAW_RTP
		// This will limit the supported formats reported from
		// Track.getSupportedFormats to only valid RTP formats.
		ContentDescriptor cd = new ContentDescriptor(ContentDescriptor.RAW_RTP);
		p.setContentDescriptor(cd);

		Format supported[];
		Format chosen;
		boolean atLeastOneTrack = false;

		// Program the tracks.
		for (int i = 0; i < tracks.length; i++) {
			Format format = tracks[i].getFormat();
			System.out.println("The track format is " +format.getEncoding());
			if (tracks[i].isEnabled()) {
				supported = tracks[i].getSupportedFormats();
				for (int n = 0; n < supported.length; n++)
					System.out.println("Supported format: " + supported[n]);

				// We've set the output content to the RAW_RTP.
				// So all the supported formats should work with RTP.
				// We'll just pick the first one.

				if (supported.length > 0) {
					chosen = supported[0]; 
					tracks[i].setFormat(chosen);
					System.err.println("Track " + i + " is set to transmit as: " +chosen);
					atLeastOneTrack = true;
				} else
					tracks[i].setEnabled(false);
			} else
				tracks[i].setEnabled(false);
		}
	}

	private void transmit(Processor p) {
		try {
			DataSource output = p.getDataOutput();
			PushBufferDataSource pbds = (PushBufferDataSource) output;
			RTPManager rtpMgr = RTPManager.newInstance();
			SessionAddress localAddr, destAddr, secDestAddr, secDestAddr1;
			SendStream sendStream;
			SourceDescription srcDesList[];
			localAddr = new SessionAddress( InetAddress.getLocalHost(), 6000);
			rtpMgr.initialize(localAddr);
			for(RadioPeer.Peer child : children){
				InetAddress childIpAddr = InetAddress.getByName(child.getAddress());
				int port1 = child.getPort()+4;
				int port2 = child.getPort()+2;
				secDestAddr = new SessionAddress(childIpAddr, port1);
				secDestAddr1 = new SessionAddress(childIpAddr, port2);
				System.err.println( "Created RTP session: " + child.getAddress() + " " + port1);
				rtpMgr.addTarget(secDestAddr);
				rtpMgr.addTarget(secDestAddr1);
			}
			sendStream = rtpMgr.createSendStream(output, 0);
			sendStream.start();
			p.start();
			
			if(createPlayer){
				System.out.println("Creating player");
				this.createPlayer();
			}
			
		} catch(Exception e) {
			e.printStackTrace();
		}
	}

	public synchronized void controllerUpdate(ControllerEvent evt) {
		System.out.println(evt.toString());
		if (evt instanceof RealizeCompleteEvent) {
			realized = true;
		} else  if (evt instanceof ConfigureCompleteEvent) {
			configured = true;
		} else if (evt instanceof EndOfMediaEvent) {
		} else {
//			System.out.println(evt.toString());
		}
	}

	public void run() {

		try {
			p = Manager.createProcessor(src);
			p.addControllerListener(this);
			p.configure();
			while (! configured) {
				try {
					Thread.currentThread().sleep(100L);;
				} catch (InterruptedException e) {
					// ignore
				}
			}

			setTrackFormat(p);
			p.setContentDescriptor(new ContentDescriptor(ContentDescriptor.RAW_RTP));

			p.realize();
			while (! realized) {
				try {
					Thread.currentThread().sleep(100L);;
				} catch (InterruptedException e) {
					// ignore
				}
			}
			transmit(p);
			
		} catch(Exception e) {
			e.printStackTrace();
			System.exit(1);
		}
	}
}